﻿
namespace TFSChangeLog.DataAccess
{
    using System;
    using System.Collections.ObjectModel;
    using System.Linq;
    using Microsoft.TeamFoundation.VersionControl.Client;
    using TFSChangeLog.DataModel;
    using TFSChangeLog.ViewModel;

    /// <summary>Summary description for <see cref="BranchDataAccess"/> class.</summary>
    public static class BranchDataAccess
    {
        #region GetBranchTree

        /// <summary>Summary description for <c>BranchDataAccess</c> method.</summary>
        /// <returns>TODO: returns an object of type <c>TFSChangeLog.DataModel.Branch</c>.</returns>
        public static Branch GetBranchTree()
        {
            var rootBranch = new Branch { Name = "ROOTPLACEHOLDER" };
            return rootBranch;
        }

        #endregion

        /// <summary>Summary description for <c>BranchDataAccess</c> method.</summary>
        /// <param name="m_ViewModel">TODO: Summary description for <c>m_ViewModel</c> parameter of type <c>TFSChangeLog.ViewModel.MainWindowViewModel</c>.</param>
        /// <returns>TODO: returns an object of type <c>TFSChangeLog.DataModel.Branch</c>.</returns>
        public static Branch GetBranchTree(MainWindowViewModel m_ViewModel)
        {
            ProgressDialogViewModel viewModel = m_ViewModel.progressDialogViewModel;
            string tfsProjectPath = "$/" + TFSConnection.GetTFSSelectedProjectName();

            string tfsBranchPath = null;

            var tfs = TFSConnection.GetTFSConnection();
            
            if (tfs != null)
            {
                var sourceControl = tfs.GetService<VersionControlServer>();
                tfsBranchPath = tfsProjectPath;
                var rootBranch = FindBranchHierarchy(sourceControl, tfsBranchPath, viewModel);

                return rootBranch;
            }

            return null;
        }

        /// <summary>Summary description for <c>BranchDataAccess</c> method.</summary>
        /// <param name="sourceControl">TODO: Summary description for <c>sourceControl</c> parameter of type <c>Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer</c>.</param>
        /// <param name="path">TODO: Summary description for <c>path</c> parameter of type <c>string</c>.</param>
        /// <param name="viewModel">TODO: Summary description for <c>viewModel</c> parameter of type <c>TFSChangeLog.ViewModel.ProgressDialogViewModel</c>.</param>
        /// <returns>TODO: returns an object of type <c>TFSChangeLog.DataModel.Branch</c>.</returns>
        private static Branch FindBranchHierarchy(VersionControlServer sourceControl, string path, ProgressDialogViewModel viewModel)
        {
            var rootBranch = new Branch { Name = "ROOTPLACEHOLDER" };

            BranchObject[] allRootBranchObjects = sourceControl.QueryRootBranchObjects(RecursionType.None);

            var activeRootBranchObjects = (from rbo in allRootBranchObjects
                                           where rbo.Properties.RootItem.IsDeleted != true
                                           select rbo);

            var allProjectRootBranchObject = (from rbo in activeRootBranchObjects
                                              where rbo.Properties.RootItem.Item.StartsWith(path)
                                              select rbo);

            foreach (var tfsRootBranch in allProjectRootBranchObject)
            {
                if (tfsRootBranch != null && !tfsRootBranch.Properties.RootItem.IsDeleted)
                {
                    var tfsRootBranchObject = new Branch { Name = tfsRootBranch.Properties.RootItem.Item.ToString() };

                    try
                    {
                        if (viewModel.TokenSource.Token.IsCancellationRequested)
                            {
                                return rootBranch;
                            }
                    }
                    catch
                    {
                    }

                    var childBranches = GetChildBranches(sourceControl, tfsRootBranch, viewModel);

                    if (childBranches != null)
                    {
                        foreach (Branch childBranch in childBranches)
                        {
                            tfsRootBranchObject.Children.Add(childBranch);
                        }
                    }

                    rootBranch.Children.Add(tfsRootBranchObject);
                }
            }

            return rootBranch;
        }

        /// <summary>Summary description for <c>BranchDataAccess</c> method.</summary>
        /// <param name="sourceControl">TODO: Summary description for <c>sourceControl</c> parameter of type <c>Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer</c>.</param>
        /// <param name="parentBranch">TODO: Summary description for <c>parentBranch</c> parameter of type <c>Microsoft.TeamFoundation.VersionControl.Client.BranchObject</c>.</param>
        /// <param name="viewModel">TODO: Summary description for <c>viewModel</c> parameter of type <c>TFSChangeLog.ViewModel.ProgressDialogViewModel</c>.</param>
        /// <returns>TODO: returns an object of type <c>System.Collections.ObjectModel.ObservableCollection{TFSChangeLog.DataModel.Branch}</c>.</returns>
        private static ObservableCollection<Branch> GetChildBranches(VersionControlServer sourceControl, BranchObject parentBranch, ProgressDialogViewModel viewModel)
        {
            var childBranches = parentBranch.ChildBranches;

            var activeRootBranchObjects = (from cbo in childBranches
                                           where cbo.IsDeleted != true
                                           select cbo);

            if (activeRootBranchObjects.ToList().Count < 1)
            {
                return null;
            }

            ObservableCollection<Branch> BranchObjects = new ObservableCollection<Branch>();

            for (int i = 0; i < childBranches.Count(); i++)
            {
                BranchObject childBranch = sourceControl.QueryBranchObjects(childBranches[i], RecursionType.None).FirstOrDefault();

                if (childBranch != null && !childBranch.Properties.RootItem.IsDeleted)
                {
                    Branch placeHolderBranchObject = new Branch { Name = childBranch.Properties.RootItem.Item };
                    var childBranchObjects = GetChildBranches(sourceControl, childBranch, viewModel);
                    if (childBranchObjects != null)
                    {
                        foreach (Branch childBranchObject in childBranchObjects)
                        {
                            try
                            {
                                if (viewModel.TokenSource.Token.IsCancellationRequested)
                                    {
                                        return BranchObjects;
                                    }
                            }
                            catch
                            {
                            }

                            placeHolderBranchObject.Children.Add(childBranchObject);
                        }
                    }

                    BranchObjects.Add(placeHolderBranchObject);
                }
            }

            return BranchObjects;
        }
    }
}
